<template>
  <div class="base-modal" :class="{ 'modal-active': isActive }" @click="handleOverlayClick">
    <div class="modal-overlay"></div>
    <div class="modal-container" :class="containerClasses" @click.stop>
      <div class="modal-header" v-if="showHeader">
        <div class="modal-title">
          <slot name="header">
            <h3 class="modal-title-text">{{ title }}</h3>
          </slot>
        </div>
        <button 
          v-if="showClose" 
          class="modal-close" 
          @click="handleClose"
          type="button"
        >
          <svg class="close-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>
      
      <div class="modal-body" :class="bodyClasses">
        <slot></slot>
      </div>
      
      <div class="modal-footer" v-if="$slots.footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'

interface Props {
  modelValue: boolean
  title?: string
  size?: 'sm' | 'md' | 'lg' | 'xl'
  width?: string | number
  showClose?: boolean
  showHeader?: boolean
  closable?: boolean
  centered?: boolean
  scrollable?: boolean
  persistent?: boolean
  zIndex?: number
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void
  (e: 'close'): void
  (e: 'open'): void
}

const props = withDefaults(defineProps<Props>(), {
  size: 'md',
  showClose: true,
  showHeader: true,
  closable: true,
  centered: true,
  scrollable: false,
  persistent: false,
  zIndex: 1000
})

const emit = defineEmits<Emits>()

const isActive = ref(false)
const isAnimating = ref(false)

const containerClasses = computed(() => [
  `modal-${props.size}`,
  {
    'modal-centered': props.centered,
    'modal-scrollable': props.scrollable
  }
])

const bodyClasses = computed(() => ({
  'modal-body-scrollable': props.scrollable
}))

watch(() => props.modelValue, async (newValue) => {
  if (newValue) {
    await open()
  } else {
    await close()
  }
})

const open = async () => {
  if (isAnimating.value) return
  
  isAnimating.value = true
  isActive.value = true
  document.body.style.overflow = 'hidden'
  
  await nextTick()
  emit('open')
  
  setTimeout(() => {
    isAnimating.value = false
  }, 300)
}

const close = async () => {
  if (isAnimating.value) return
  
  isAnimating.value = true
  
  setTimeout(() => {
    isActive.value = false
    document.body.style.overflow = ''
    isAnimating.value = false
    emit('close')
  }, 200)
}

const handleClose = () => {
  if (props.closable && !isAnimating.value) {
    emit('update:modelValue', false)
  }
}

const handleOverlayClick = () => {
  if (!props.persistent && props.closable) {
    handleClose()
  }
}

const handleEscape = (event: KeyboardEvent) => {
  if (event.key === 'Escape' && props.closable && !props.persistent) {
    handleClose()
  }
}

onMounted(() => {
  if (props.modelValue) {
    open()
  }
  document.addEventListener('keydown', handleEscape)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleEscape)
  document.body.style.overflow = ''
})
</script>

<style scoped>
.base-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: v-bind(zIndex);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  opacity: 0;
  visibility: hidden;
  transition: all 0.2s ease;
}

.modal-active {
  opacity: 1;
  visibility: visible;
}

.modal-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px);
}

.modal-container {
  position: relative;
  background: var(--card-bg);
  border-radius: 12px;
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  max-height: calc(100vh - 32px);
  display: flex;
  flex-direction: column;
  transform: scale(0.9) translateY(20px);
  transition: all 0.2s ease;
  border: 1px solid var(--border);
}

.modal-active .modal-container {
  transform: scale(1) translateY(0);
}

.modal-sm {
  width: 100%;
  max-width: 400px;
}

.modal-md {
  width: 100%;
  max-width: 600px;
}

.modal-lg {
  width: 100%;
  max-width: 800px;
}

.modal-xl {
  width: 100%;
  max-width: 1000px;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.modal-title {
  flex: 1;
  margin: 0;
}

.modal-title-text {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  margin: 0;
}

.modal-close {
  background: none;
  border: none;
  padding: 8px;
  margin: -8px;
  cursor: pointer;
  border-radius: 6px;
  color: var(--text-muted);
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-close:hover {
  background: var(--bg-secondary);
  color: var(--text);
}

.close-icon {
  width: 20px;
  height: 20px;
}

.modal-body {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
}

.modal-body-scrollable {
  max-height: calc(100vh - 200px);
}

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 16px 24px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-secondary);
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
}

.modal-centered {
  align-items: center;
}

.modal-scrollable .modal-body {
  max-height: calc(100vh - 200px);
  overflow-y: auto;
}

/* 暗色模式支持 */
@media (prefers-color-scheme: dark) {
  .modal-container {
    background: var(--card-bg);
    border-color: var(--border);
  }
  
  .modal-header {
    border-color: var(--border-light);
  }
  
  .modal-footer {
    background: var(--bg-secondary);
    border-color: var(--border-light);
  }
}

/* 响应式设计 */
@media (max-width: 640px) {
  .base-modal {
    padding: 8px;
  }
  
  .modal-container {
    margin: 0;
    max-height: calc(100vh - 16px);
  }
  
  .modal-header {
    padding: 16px 20px;
  }
  
  .modal-body {
    padding: 20px;
  }
  
  .modal-footer {
    padding: 12px 20px;
  }
  
  .modal-sm,
  .modal-md {
    max-width: 100%;
  }
}

/* 动画优化 */
@keyframes modalEnter {
  from {
    opacity: 0;
    transform: scale(0.9) translateY(20px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes modalExit {
  from {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
  to {
    opacity: 0;
    transform: scale(0.9) translateY(20px);
  }
}
</style>